/**
 * @file oled.h
 * @brief OLED SSD1306 驱动头文件 (DMA缓存模式)
 * @version 2.0
 * @date 2025-10-03
 * 
 * 本驱动采用硬件SPI + DMA自动刷新模式
 * 特点：无需中断，无需手动刷新，只需修改缓存，硬件自动显示
 */

#ifndef __OLED_H
#define __OLED_H

#include "config.h"

// ========== 基础定义 ==========
#define OLED_CMD  0     // 命令模式
#define OLED_DATA 1     // 数据模式

// OLED 屏幕尺寸定义
#define OLED_WIDTH  128     // 屏幕宽度（像素）
#define OLED_HEIGHT 64      // 屏幕高度（像素）
#define OLED_PAGES  8       // 页数 (64/8 = 8页)

// 显示缓存大小：128 × 64 ÷ 8 = 1024 字节
#define OLED_BUFFER_SIZE (OLED_WIDTH * OLED_PAGES)

// ========== 初始化和控制函数 ==========
/**
 * @brief OLED初始化（会自动配置DMA并启动自动刷新）
 */
extern void OLED_Init(void);

/**
 * @brief 显示开启
 */
extern void OLED_Display_On(void);

/**
 * @brief 显示关闭
 */
extern void OLED_Display_Off(void);

/**
 * @brief 颜色反转
 * @param i 0=正常显示, 1=反色显示
 */
extern void OLED_ColorTurn(uint8_t i);

/**
 * @brief 屏幕旋转180度
 * @param i 0=正常显示, 1=旋转180度
 */
extern void OLED_DisplayTurn(uint8_t i);

// ========== 传统直接写入函数（兼容旧代码）==========
/**
 * @brief 写入一个字节（命令或数据）
 * @param dat 要写入的数据
 * @param cmd OLED_CMD=命令, OLED_DATA=数据
 */
extern void OLED_WR_Byte(uint8_t dat, uint8_t cmd);

/**
 * @brief 设置光标位置
 * @param x 列地址 (0-127)
 * @param y 页地址 (0-7)
 */
extern void OLED_Set_Pos(uint8_t x, uint8_t y);

/**
 * @brief 清屏（使用直接写入方式）
 */
extern void OLED_Clear(void);

/**
 * @brief 填充整个屏幕（使用直接写入方式）
 * @param dat 填充数据 (0x00=全黑, 0xFF=全白)
 */
extern void OLED_Fill(uint8_t dat);

// ========== DMA缓存模式函数（推荐使用）==========
/**
 * @brief 获取显示缓存指针
 * @return 显示缓存的指针
 * @note 可用于高级操作，直接修改缓存内容
 */
extern uint8_t* OLED_GetBuffer(void);

/**
 * @brief 清空显示缓存（填充为0x00）
 */
extern void OLED_ClearBuffer(void);

/**
 * @brief 填充整个缓存
 * @param color 填充的颜色值 (0x00=黑, 0xFF=白)
 */
extern void OLED_FillBuffer(uint8_t color);

/**
 * @brief 启动DMA循环传输
 * @note 在OLED_Init中自动调用，通常无需手动调用
 */
extern void OLED_StartDMA(void);

/**
 * @brief 暂停DMA传输（保留当前进度）
 */
extern void OLED_PauseDMA(void);

/**
 * @brief 恢复DMA传输（从暂停位置继续）
 */
extern void OLED_ResumeDMA(void);

/**
 * @brief 停止DMA传输
 * @note 如果需要临时停止自动刷新
 */
extern void OLED_StopDMA(void);

/**
 * @brief 重新启动DMA传输
 * @note 如果之前停止过，使用此函数恢复
 */
extern void OLED_RestartDMA(void);

// ========== 绘图函数（操作缓存）==========
/**
 * @brief 在缓存中设置像素点
 * @param x X坐标 (0-127)
 * @param y Y坐标 (0-63)
 * @param color 颜色 (0=黑色, 1=白色)
 */
extern void OLED_DrawPixel(uint8_t x, uint8_t y, uint8_t color);

/**
 * @brief 在缓存中绘制水平线
 * @param x 起始X坐标 (0-127)
 * @param y Y坐标 (0-63)
 * @param w 线的宽度（像素数）
 * @param color 颜色 (0=黑色, 1=白色)
 */
extern void OLED_DrawHLine(uint8_t x, uint8_t y, uint8_t w, uint8_t color);

/**
 * @brief 在缓存中绘制垂直线
 * @param x X坐标 (0-127)
 * @param y 起始Y坐标 (0-63)
 * @param h 线的高度（像素数）
 * @param color 颜色 (0=黑色, 1=白色)
 */
extern void OLED_DrawVLine(uint8_t x, uint8_t y, uint8_t h, uint8_t color);

/**
 * @brief 在缓存中绘制矩形边框
 * @param x 左上角X坐标 (0-127)
 * @param y 左上角Y坐标 (0-63)
 * @param w 矩形宽度
 * @param h 矩形高度
 * @param color 颜色 (0=黑色, 1=白色)
 */
extern void OLED_DrawRect(uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint8_t color);

/**
 * @brief 在缓存中填充矩形
 * @param x 左上角X坐标 (0-127)
 * @param y 左上角Y坐标 (0-63)
 * @param w 矩形宽度
 * @param h 矩形高度
 * @param color 颜色 (0=黑色, 1=白色)
 */
extern void OLED_FillRect(uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint8_t color);

// ========== 字符显示函数 ==========
/**
 * @brief 在缓存中绘制一个字符（5x7字体）
 * @param x X坐标 (0-127)
 * @param y Y坐标 (0-63)
 * @param ch 要显示的字符（ASCII 32-126）
 * @param color 颜色 (0=黑色, 1=白色)
 * @return 返回字符宽度（用于连续显示）
 */
extern uint8_t OLED_DrawChar(uint8_t x, uint8_t y, char ch, uint8_t color);

/**
 * @brief 在缓存中显示字符串（5x7字体）
 * @param x 起始X坐标 (0-127)
 * @param y 起始Y坐标 (0-63)
 * @param str 要显示的字符串
 * @param color 颜色 (0=黑色, 1=白色)
 * @note 支持自动换行，支持'\n'换行符
 */
extern void OLED_DrawString(uint8_t x, uint8_t y, const char* str, uint8_t color);

/**
 * @brief 在缓存中显示整数
 * @param x X坐标 (0-127)
 * @param y Y坐标 (0-63)
 * @param num 要显示的整数（支持负数）
 * @param color 颜色 (0=黑色, 1=白色)
 */
extern void OLED_DrawNumber(uint8_t x, uint8_t y, int32_t num, uint8_t color);

/**
 * @brief 在缓存中显示浮点数
 * @param x X坐标 (0-127)
 * @param y Y坐标 (0-63)
 * @param num 要显示的浮点数
 * @param decimal 小数点后位数 (0-6)
 * @param color 颜色 (0=黑色, 1=白色)
 */
extern void OLED_DrawFloat(uint8_t x, uint8_t y, float num, uint8_t decimal, uint8_t color);

#endif // __OLED_H
